package studio.raptor.ddal.dashboard.rule;

import studio.raptor.ddal.common.algorithm.ShardValue;
import studio.raptor.ddal.common.algorithm.SingleKeyShardAlgorithm;

import java.util.Collection;

/**
 * 分片算法：字符型字段hash后再取模路由
 *
 */
public class TestHashAndModSingleKeyShardAlgorithm implements SingleKeyShardAlgorithm<Comparable<?>> {

    private final int count;

    public TestHashAndModSingleKeyShardAlgorithm(String param) {
        this.count = Integer.valueOf(param);
    }

    /**
     * 分片算法：字符型字段hash后再取模路由
     * 根据分片值和SQL的=运算符计算分片结果名称集合.
     *
     * @param shards 所有的可用目标名称集合, 一般是数据源或表名称
     * @param shardValue 分片值
     * @return 分片后指向的目标名称, 一般是数据源或表名称
     */
    public String doEqual(Collection<String> shards, ShardValue<Comparable<?>> shardValue) {
        int length=String.valueOf(shardValue.getValue()).length();
//        int value = String.valueOf(shardValue.getValue()).hashCode();
        int value = hash(String.valueOf(shardValue.getValue()));
        for (String shard : shards) {
            if (shard.endsWith(value % count + "")) {
                return shard;
            }
        }
        throw new UnsupportedOperationException();
    }

    /**
     * 根据分片值和SQL的IN运算符计算分片结果名称集合.
     *
     * @param shards 所有的可用目标名称集合, 一般是数据源或表名称
     * @param shardValue 分片值
     * @return 分片后指向的目标名称集合, 一般是数据源或表名称
     */
    @Override
    public Collection<String> doIn(Collection<String> shards, ShardValue<Comparable<?>> shardValue) {
        return null;
    }

    /**
     * 根据分片值和SQL的BETWEEN运算符计算分片结果名称集合.
     *
     * @param shards 所有的可用目标名称集合, 一般是数据源或表名称
     * @param shardValue 分片值
     * @return 分片后指向的目标名称集合, 一般是数据源或表名称
     */
    @Override
    public Collection<String> doBetween(Collection<String> shards,
                                        ShardValue<Comparable<?>> shardValue) {
        return null;
    }


    public static int hash(Object key) {
        int h;
        int hashValue= (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
        if(hashValue<0){
            hashValue=hashValue*(-1);
        }
        return hashValue;
    }
}
